package net.bplaced.streetfighter.fragment;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import net.bplaced.streetfighter.R;
import net.bplaced.streetfighter.adapter.MatchAdapter;
import net.bplaced.streetfighter.lib.async.task.MatchLoaderTask;
import net.bplaced.streetfighter.lib.model.Match;
import net.bplaced.streetfighter.lib.utils.CallBack;
import net.bplaced.streetfighter.lib.utils.RuntimeData;
import net.bplaced.streetfighter.lib.utils.RuntimeDataKey;
import net.bplaced.streetfighter.lib.utils.RuntimeDataObject;
import net.bplaced.streetfighter.lib.utils.ServiceReturnPackage;
import net.bplaced.streetfighter.lib.utils.StreetfighterUtils;
import android.app.DatePickerDialog;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Events;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;

/**
 * @author Sebastian Hoffmann <bo.hoffi@googlemail.com>
 */
public class MatchesFragment
        extends Fragment {

    private RelativeLayout view = null;

    private Button searchDateButton;
    private Calendar selectedDate;
    private Match contextMenuMatch = null;

    private MatchAdapter matchAdapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        this.view = (RelativeLayout) inflater.inflate(R.layout.view_matches, container, false);

        this.prepareView();

        return this.view;
    }

    private void prepareView() {

        this.matchAdapter = new MatchAdapter(this.getActivity(), new ArrayList<Match>(), this);
        final ListView matchList = (ListView) this.view.findViewById(R.id.matchList);
        matchList.setAdapter(this.matchAdapter);

        if (RuntimeData.getInstance().get(RuntimeDataKey.MATCH_SEARCH_RESULT) != null) {

            this.matchAdapter.addAll((Match[]) RuntimeData.getInstance().get(RuntimeDataKey.MATCH_SEARCH_RESULT)
                    .getData());
        }

        this.searchDateButton = (Button) this.view.findViewById(R.id.searchDateButton);
        this.searchDateButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                new DatePickerDialog(MatchesFragment.this.getActivity(), MatchesFragment.this.mDateSetListener,
                        MatchesFragment.this.selectedDate.get(Calendar.YEAR), MatchesFragment.this.selectedDate
                                .get(Calendar.MONTH), MatchesFragment.this.selectedDate.get(Calendar.DAY_OF_MONTH))
                        .show();
            }
        });

        final Button startSearchBtn = (Button) this.view.findViewById(R.id.startSearchButton);
        startSearchBtn.setOnClickListener(this.searchButtonClickListener);

        this.setActualDate();
    }

    /**
     * Deklariert einen Callback, welcher zum Ende des Serviceaurufes aufgerufen wird.
     */
    private final CallBack<ServiceReturnPackage<Match[]>> onFinishedLoading =
            new CallBack<ServiceReturnPackage<Match[]>>() {

                @Override
                public void callbackAction(ServiceReturnPackage<Match[]> result) {

                    if (result != null) {
                        if (result.getContent() != null) {

                            MatchesFragment.this.matchAdapter.clear();
                            MatchesFragment.this.matchAdapter.addAll(result.getContent());
                            RuntimeData.getInstance().put(RuntimeDataKey.MATCH_SEARCH_RESULT,
                                    new RuntimeDataObject<Match[]>(result.getContent()));

                        } else {

                            Toast.makeText(MatchesFragment.this.getActivity(), result.getErrorMessage(),
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                };
            };

    /**
     * Sets the displayed date to the actual one.
     */
    private void setActualDate() {

        this.selectedDate = Calendar.getInstance();

        this.updateDisplay();
    }

    /**
     * Updates the displayed date on the view to the selected one.
     */
    private void updateDisplay() {

        this.searchDateButton.setText(new SimpleDateFormat("dd.MM.yyyy").format(this.selectedDate.getTime()));
    }

    /**
     * The callback, when the user "sets" a date on the DatePickerDialog.
     */
    private final DatePickerDialog.OnDateSetListener mDateSetListener = new DatePickerDialog.OnDateSetListener() {

        @Override
        public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {

            MatchesFragment.this.selectedDate.set(year, monthOfYear, dayOfMonth);

            MatchesFragment.this.updateDisplay();
        }
    };

    /**
     * The callback, when the user starts the search.
     */
    private final View.OnClickListener searchButtonClickListener = new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            final MatchLoaderTask task =
                    new MatchLoaderTask(MatchesFragment.this.getActivity(), MatchesFragment.this.getResources()
                            .getString(R.string.matches_progress_message), MatchesFragment.this.onFinishedLoading);
            task.execute(MatchesFragment.this.selectedDate.getTime());
        }
    };

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

        // Hack for the menu item to appear only once
        if (menu.size() == 0) {
            menu.add(0, 0, 0, this.getResources().getString(R.string.matches_context_menu_add));
        }

        // Hack to get the comment of the context menu
        this.contextMenuMatch = (Match) v.getTag();
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {

        final Match match = this.contextMenuMatch;

        if (match != null) {
            this.createCalendarEntry(match);
        }

        return false;
    }

    private void createCalendarEntry(Match match) {

        final Intent calIntent = new Intent(Intent.ACTION_EDIT);
        calIntent.setType("vnd.android.cursor.item/event");
        calIntent.putExtra(Events.TITLE, match.opponent);
        calIntent.putExtra(
                Events.EVENT_LOCATION,
                new StringBuilder(match.locationName).append(", ").append(match.locationStreet).append(",")
                        .append(match.locationPostCode).append(" ").append(match.locationCity).toString());
        calIntent.putExtra(Events.DESCRIPTION, StreetfighterUtils.parseMatchCategory(match.matchCategory));
        calIntent.putExtra(Events.GUESTS_CAN_INVITE_OTHERS, false);
        calIntent.putExtra(Events.GUESTS_CAN_MODIFY, false);

        final Date date = StreetfighterUtils.convertToDate(match.matchDate, match.matchTime);
        final GregorianCalendar calDate = new GregorianCalendar();
        calDate.setTime(date);
        calIntent.putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, false);
        calIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, calDate.getTimeInMillis());
        calDate.add(Calendar.MINUTE, 105);
        calIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, calDate.getTimeInMillis());

        calIntent.putExtra(Events.ACCESS_LEVEL, Events.ACCESS_PRIVATE);
        calIntent.putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY);

        this.getActivity().startActivity(calIntent);
    }
}